package com.zhuqi.redis.list;

import io.netty.util.concurrent.DefaultThreadFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author : ZhuQi
 * @version : 时间:2022/1/10 10:37 版本:
 * 使用 redis list 建立一个生产者消费者模型
 */
@Component
@Slf4j
public class ProducerAndConsumer {

    final static ThreadPoolExecutor task =
            new ThreadPoolExecutor(10,
                    20,
                    5L,
                    TimeUnit.SECONDS,
                    new LinkedBlockingDeque<>(10),
                    new DefaultThreadFactory("task"));

//    @Autowired
//    private StringRedisTemplate stringRedisTemplate;

    /**
     * 队列名
     */
    private final String workerQueueName = "ORDER_QUEUE";


    volatile Thread producerThread;

    volatile Thread consumerThread1;

    volatile Thread consumerThread2;

    volatile Thread consumerThread3;

    private static Unsafe unsafe;

    @Autowired
    private ApplicationContext applicationContext;

    static {
        Field theUnsafe = null;
        try {
            theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        theUnsafe.setAccessible(true);
        try {
            unsafe = (Unsafe) theUnsafe.get(null);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试内容:
     */
    @SuppressWarnings("uncheck")
    public void test() throws Exception {


        // 一个生产者 从队列左侧插入数据
        task.execute(() -> {
            RedisTemplate stringRedisTemplate = (RedisTemplate)applicationContext.getBean("stringRedisTemplate");
            ListOperations<String, String> stringStringListOperations =
                    stringRedisTemplate.opsForList();
            producerThread = Thread.currentThread();
            producerThread.setName("prod-thread");

            int i = 0;
            while (true) {
                ++i;
                String name = "订单号";
                stringStringListOperations.leftPush(workerQueueName, "订单号" + i);
                log.info("生产线程生产了消息:{}", "订单号" + i);
                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        // 消费线程1
        task.execute(() -> {
            RedisTemplate stringRedisTemplate = (RedisTemplate)applicationContext.getBean("stringRedisTemplate");
            ListOperations<String, String> stringStringListOperations =
                    stringRedisTemplate.opsForList();
            consumerThread1 = Thread.currentThread();
            consumerThread1.setName("consumer-thread1");
            while (true) {
                String data = stringStringListOperations.rightPop(workerQueueName);
                log.info("消费线程正在处理数据:{}", data);
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        // 消费线程2
        task.execute(() -> {
            RedisTemplate stringRedisTemplate = (RedisTemplate)applicationContext.getBean("stringRedisTemplate");
            ListOperations<String, String> stringStringListOperations =
                    stringRedisTemplate.opsForList();
            consumerThread2 = Thread.currentThread();
            consumerThread2.setName("consumer-thread2");
            while (true) {
                String data = stringStringListOperations.rightPop(workerQueueName);
                log.info("消费线程正在处理数据:{}", data);
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });


        // 消费线程3
        task.execute(() -> {
            RedisTemplate stringRedisTemplate = (RedisTemplate)applicationContext.getBean("stringRedisTemplate");
            ListOperations<String, String> stringStringListOperations =
                    stringRedisTemplate.opsForList();
            consumerThread3 = Thread.currentThread();
            consumerThread3.setName("consumer-thread3");
            while (true) {
                String data = stringStringListOperations.rightPop(workerQueueName);
                log.info("消费线程正在处理数据:{}", data);
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });


    }



}
